﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Windows.Forms;
using System.IO;
using CryForLua_wpf_AvEd.UserPreferences;

namespace CryForLua_wpf_AvEd.CodeCompletion
{
    public class AutoCompletitionManager
    {
        public UserPreferencesData Pref_Data = UserPreferencesData.Instance;


        public void SearchDirectories()
        {
             string[] htmFiles = null;
             try
             {
                 htmFiles = Directory.GetFiles(Pref_Data.htmFilesDir, "*.htm", SearchOption.AllDirectories);
             }
             catch (Exception e)
             {
                 MessageBox.Show("No valid path specified for HTM Files directory, specify in User Preferences and try again! \nError message: " + e.Message);
                 return;
             }

            if (htmFiles.Length == 0)
            {
                MessageBox.Show("Couldn't find any htm files, please make sure you have selected the correct folder under Edit->Preferences!",
                    "ERROR",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);

                return;
            }

            foreach (string file in htmFiles)
            {
                if (true)
                {

                    TextReader reader = new StreamReader(file);


                    string content = reader.ReadToEnd();


                    int fileNameStart = file.LastIndexOf("\\") + "\\ScriptBind_".Length;
                    int fileNameEnd = file.Length - ".htm".Length;


                    string filename = file.Substring(fileNameStart, fileNameEnd - fileNameStart);


                    reader.Close();

                    // Pretty ugly but ScriptBind_AI has different formatting that the rest :(
                    // And wth is wrong with GameRules? O.O

                    if (filename == "AI")
                    {
                        SearchAITypeFormat(content);
                    }
                    else
                    {
                        SearchElementTypeFormat(content, filename);
                    }

                
                    CodeTable.Instance.SaveGlobalTableToFile();

                    // Gosh i cant believe this works on the first try...
                }
            }

        }

      

        private void ParseFunctionDefinition(ref CodeTable.LuaFunction function)
        {
            if (function == null || function.paramList == null || function.paramList.Count != 0 || function.name == "")
            {
                if (function != null && function.paramList == null)
                {
                    function.paramList = new List<CodeTable.LuaParameter>();
                }
                else
                    return;
            }

           
            int paramCount = function.name.Count(f => f == ',') + 1;
            int commaStart = 0;
            int lastComma = 0;

            if (paramCount == 1)
            {
                int par = function.name.IndexOf('(');

                if (par == -1)
                    return;

                int parEnd = function.name.IndexOf(')');

                if (parEnd == -1)
                    return;

                if (par + 1 == parEnd)
                    return;

                string paramName = function.name.Substring(++par, parEnd - par);

                function.paramList.Add(new CodeTable.LuaParameter(paramName, "<Missing Description>"));
            }
            else
            {
                while (commaStart != -1)
                {
                    commaStart = function.name.IndexOf(',', commaStart + 1);

                    if (commaStart == -1)
                    {
                        int functionEnd = function.name.IndexOf(')');

                        if (functionEnd == -1)
                            return;

                        int paramStart = function.name.LastIndexOf(',', functionEnd) + 1;

                        function.paramList.Add(new CodeTable.LuaParameter(function.name.Substring(paramStart, functionEnd - paramStart), "<Missing Description>"));
                        break;
                    }

                    if (lastComma == 0)
                    {
                        int paramsStart = function.name.IndexOf('(');

                        if (paramsStart == -1)
                            return;

                        ++paramsStart;
                        function.paramList.Add(new CodeTable.LuaParameter(function.name.Substring(paramsStart, commaStart - paramsStart), "<Missing Description>"));

                        lastComma = commaStart + 1;

                    }
                    else
                    {
                        function.paramList.Add(new CodeTable.LuaParameter(function.name.Substring(lastComma, commaStart - lastComma), "<Missing Description>"));
                        lastComma = commaStart + 1;
                    }



                }


            }

            
        }

        
        /// <summary>
        /// Searches ScriptBind_AI.htm 
        /// </summary>
        public void SearchAITypeFormat(string fileContent)
        {
            int curPos = 0;
            int curEndPos = 0;
            bool isFunction = true;

            do
            {
                curPos = fileContent.IndexOf("mce_tmp=\"1\">", curPos);

                if (curPos == -1)
                    break;

                curEndPos = fileContent.IndexOf("</HR>", curPos + 1);

                if (curEndPos == -1)
                    break;

                int finalPos = curPos + ("mce_tmp=\"1\">".Length);
                int length = curEndPos - finalPos;

                char[] buffer = new char[length];

                fileContent.CopyTo(finalPos, buffer, 0, length);

                string result = new string(buffer);

                // This is dangerous but it's pretty unlikely that curPos will ever be the very last character

                if (result.Contains("<STRONG>"))
                {
                    int skipPos = result.IndexOf("</STRONG>);", 0); //This is the case for some functions.. ill see what i can do about it
                    curPos += "</STRONG>);".Length + 1;
                    isFunction = false;                             // Technically it is still a function but it's a pain in the a** to extract all the html stuff
                }
                else
                    curPos++;

                if (isFunction == true)
                {
                    CodeTable.LuaFunction function = new CodeTable.LuaFunction();

                    // The actual searching happens here
                    string functionName = ""; ;

                    int nameStart = result.IndexOf("AI.") + "AI.".Length;
                    int nameEnd = result.IndexOf(")", nameStart + 1) + 1;

                    functionName = result.Substring(nameStart, nameEnd - nameStart);

                    function.name = functionName;
                    // Function description
                    string functionDescription = "";
                    int descStart = result.IndexOf("<P class=\"Element10\">", nameEnd);
                    int descEnd = 0;
                    if (descStart != -1)
                    {
                        descStart += "<P class=\"Element10\">".Length;
                        descEnd = result.IndexOf("</P>", descStart);

                        functionDescription = result.Substring(descStart, descEnd - descStart);

                    }
                    else
                    {
                        functionDescription = "<Missing description>";
                        descEnd = nameEnd;
                    }

                    function.description = functionDescription;

                    // Function parameterlist
                    // firts param name (Element243) then desc (Element247)
                    // BEWARE OF FLAGS!

                    int paramNameStart = descEnd + 1;

                    // while loop here
                    do
                    {

                        paramNameStart = result.IndexOf("<DIV class=\"Element243\">", paramNameStart);

                        if (paramNameStart == -1)
                            break;

                        paramNameStart += "<DIV class=\"Element243\">".Length;

                        int paramNameEnd = result.IndexOf("</DIV>", paramNameStart + 1);

                        string daname = result.Substring(paramNameStart, paramNameEnd - paramNameStart);

                        int paramDescStart = result.IndexOf("<DIV class=\"Element247\">", paramNameEnd + 1) + "<DIV class=\"Element247\">".Length;
                        int paramDescEnd = result.IndexOf("</DIV>", paramDescStart + 1);

                        string dadesc = result.Substring(paramDescStart, paramDescEnd - paramDescStart);

                        CodeTable.LuaParameter param = new CodeTable.LuaParameter(daname, dadesc);
                        function.paramList.Add(param);

                        paramNameStart = paramDescEnd + 1;

                    } while (paramNameStart != -1);

                    // Return value

                    string functionReturnValue = "";
                    int retValStart = result.IndexOf("<P class=\"Element10\">", descEnd);
                    int retValEnd = 0;

                    if (retValStart != -1)
                    {
                        retValStart += "<P class=\"Element10\">".Length;
                        retValEnd = result.IndexOf("</P>", retValStart);

                        functionReturnValue = result.Substring(retValStart, retValEnd - retValStart);
                    }
                    else
                    {

                        functionReturnValue = "<None / Not specified (see desc)>";
                    }

                    function.returnValue = functionReturnValue;

                    // while ends here

                    ParseFunctionDefinition(ref function);

                    CodeTable.LuaFunctionTableBlah meh = new CodeTable.LuaFunctionTableBlah();

                    bool ok = CodeTable.TABLE.TryGetValue("AI", out meh);

                    meh.classFunctions.Add(function);
                }

                isFunction = true;

                // TODO 
                // Replace this with actual code
                // DialogResult whilestopper = MessageBox.Show("NOES", "HEHE", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);

                //if (whilestopper == DialogResult.Cancel )
                //{
                //    break;
                //}
            } while (curPos != -1);
        }


        /// <summary>
        /// Searches everything but ScriptBind_AI.htm
        /// </summary>
        public void SearchElementTypeFormat(string fileContent, string fileName)
        {
            int curPos = 0;
            int curEndPos = 0;
            bool isFunction = true;


            string className = fileName;


            do
            {
                // More tricky
                // Need to extract the whole block of data...
                curPos = fileContent.IndexOf("<hr /><A name=", curPos);

                if (curPos == -1)
                    break;

                // End pos is where the next block starts
                curEndPos = fileContent.IndexOf("<hr /><A name=", curPos + 1);

                if (curEndPos == -1)
                {
                    curEndPos = fileContent.IndexOf("<HR>", curPos + 1);

                    if (curEndPos == -1)
                    {
                        break;
                    }
                }

                int finalPos = curPos;
                int length = curEndPos - finalPos;

                char[] buffer = new char[length];

                fileContent.CopyTo(finalPos, buffer, 0, length);

                string result = new string(buffer);

                // This is dangerous but it's pretty unlikely that curPos will ever be the very last character

                if (result.Contains("<STRONG>"))
                {
                    int skipPos = result.IndexOf("</STRONG>);", 0); //This is the case for some functions.. ill see what i can do about it
                    curPos += "</STRONG>);".Length + 1;
                    isFunction = false;                             // Technically it is still a function but it's a pain in the a** to extract all the html stuff
                }
                else
                    curPos++;

                if (isFunction == true)
                {
                    CodeTable.LuaFunction function = new CodeTable.LuaFunction();

                    // The actual searching happens here
                    string functionName = ""; ;

                    int nameStart = result.IndexOf("<pre class=\"Element100\"> ");
                    nameStart += "<pre class=\"Element100\"> ".Length + className.Length + 1; // +1 resembles the dot betwwen classname and functionname

                    int nameEnd = result.IndexOf(")", nameStart + 1) + 1;

                    functionName = result.Substring(nameStart, nameEnd - nameStart);

                    function.name = functionName;
                    // Function description
                    string functionDescription = "";
                    int descStart = result.IndexOf("<p class=\"Element10\">", nameEnd);
                    int descEnd = 0;
                    if (descStart != -1)
                    {
                        descStart += "<p class=\"Element10\">".Length;
                        descEnd = result.IndexOf("</p>", descStart);

                        functionDescription = result.Substring(descStart, descEnd - descStart);

                    }
                    else
                    {
                        functionDescription = "<Missing description>";
                        descEnd = nameEnd;
                    }

                    function.description = functionDescription;

                    // Function parameterlist
                    // firts param name (Element243) then desc (Element247)
                    // BEWARE OF FLAGS!

                    int paramNameStart = descEnd + 1;

                    // while loop here
                    do
                    {

                        paramNameStart = result.IndexOf("<div class=\"Element243\">", paramNameStart);

                        if (paramNameStart == -1)
                            break;

                        paramNameStart += "<div class=\"Element243\">".Length;

                        int paramNameEnd = result.IndexOf("</div>", paramNameStart + 1) - "&nbsp;".Length;

                        string daname = result.Substring(paramNameStart, paramNameEnd - paramNameStart);

                        int paramDescStart = result.IndexOf("<div class=\"Element247\">", paramNameEnd + 1) + "<div class=\"Element247\">".Length;
                        int paramDescEnd = result.IndexOf("</div>", paramDescStart + 1) - "&nbsp;".Length;

                        string dadesc = result.Substring(paramDescStart, paramDescEnd - paramDescStart);

                        CodeTable.LuaParameter param = new CodeTable.LuaParameter(daname, dadesc);
                        function.paramList.Add(param);

                        paramNameStart = paramDescEnd + 1;

                    } while (paramNameStart != -1);

                    // while ends here

                    string functionReturnValue = "";
                    int retValStart = result.IndexOf("<p class=\"Element10\">", descEnd);
                    int retValEnd = 0;

                    if (retValStart != -1)
                    {
                        retValStart += "<p class=\"Element10\">".Length + 1;
                        retValEnd = result.IndexOf("</p>", retValStart);

                        functionReturnValue = result.Substring(retValStart, retValEnd - retValStart);
                    }
                    else
                    {

                        functionReturnValue = "<None / Not specified (see desc)>";
                    }

                    function.returnValue = functionReturnValue;

                    ParseFunctionDefinition(ref function);

                    CodeTable.LuaFunctionTableBlah meh = new CodeTable.LuaFunctionTableBlah();

                    bool ok = CodeTable.TABLE.TryGetValue(className, out meh);

                    meh.classFunctions.Add(function);
                }

                isFunction = true;

                // TODO 
                // Replace this with actual code
                // DialogResult whilestopper = MessageBox.Show("NOES", "HEHE", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation);

                //if (whilestopper == DialogResult.Cancel )
                //{
                //    break;
                //}
            } while (curPos != -1);
        }


        public void SearchCurrentDocument(ref RichTextBox richTextBox)
        {
            string text = richTextBox.Text;
            //------------------------------------------------------
            List<String> reloadedScripts = new List<string>();
            int reloadDirectivePos = 0;
            //------------------------------------------------------
            List<CodeTable.LuaFunction> functions = new List<CodeTable.LuaFunction>();
            int functionPos = 0;
            int functionEndPos = 0;



            #region Search reload statements

            do
            {
                reloadDirectivePos = text.IndexOf("ReloadScript(\""); // Doesn't work because we're searching only whole strings

                if (reloadDirectivePos != -1)
                {
                    int length = "Script.ReloadScript(\"".Length;

                    reloadedScripts.Add((text.Substring(reloadDirectivePos + length, text.IndexOf("\");") - reloadDirectivePos + length)));
                }

            } while (reloadDirectivePos != -1);

            #endregion

            #region Search functions

            do
            {
                //TODO
                //Prolly gotta use regex here- no works
                //Move this to seperate function
                //Search all reloaded sripts with it


                functionPos = text.IndexOf("function", functionPos);


                if (functionPos >= text.Length)
                    break;

                if (functionPos == -1)
                    break;

                functionPos += "function".Length + 1;

                functionEndPos = text.IndexOf(")", functionPos) + 1;

                string funcName = text.Substring(functionPos, functionEndPos - functionPos);

                functions.Add(CodeTable.LuaFunction.BuildLuaFunction(funcName));




            } while (functionPos != -1);

            CodeTable.TABLE.Add("CurrentDoc", new CodeTable.LuaFunctionTableBlah(functions));

            #endregion
        }

    }
}
